import { DOCUMENT } from '@angular/common';
import { ApplicationRef, ComponentFactoryResolver, ComponentRef, EmbeddedViewRef, Inject, Injectable, Injector, Type } from '@angular/core';


export interface DialogPos {
  top: string;
  left: string;
  width: string;
  height: string;
}

export interface ChildConfig {
  inputs: object;
  outputs: object;
  position?: DialogPos;
}

@Injectable({providedIn: 'root'})
export class DomService {

  private childComponentRef: ComponentRef<any>;

  constructor(
    private resolver: ComponentFactoryResolver,
    private appRef: ApplicationRef,
    private injector: Injector,
    @Inject(DOCUMENT) private document: Document
  ) { }



  public appendComponentTo(
    parentId: string,
    child: Type<any>,
    childConfig: ChildConfig
    ): void {
    const childComponentRef =  this.resolver.resolveComponentFactory(child).create(this.injector);
    this.attachConfig(childConfig, childComponentRef);
    this.childComponentRef = childComponentRef;
    this.appRef.attachView(childComponentRef.hostView);
    const childDomElement = (childComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
    this.document.getElementById(parentId).appendChild(childDomElement);

  }

  public attachConfig(config: ChildConfig, componentRef: ComponentRef<any>): void {
    const {inputs, outputs} = config;
    for (const key in inputs) {
      if (Object.prototype.hasOwnProperty.call(inputs, key)) {
        const element = inputs[key];
        componentRef.instance[key] = element;
      }
    }

    for (const key in outputs) {
      if (Object.prototype.hasOwnProperty.call(outputs, key)) {
        const element = outputs[key];
        componentRef.instance[key] = element;
      }
    }
  }

  public removeComponent() {
    this.appRef.detachView(this.childComponentRef.hostView)
  }

}
